package com.htgd.gardenexpo.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.htgd.gardenexpo.controller.CommonController;
import com.htgd.gardenexpo.dao.*;
import com.htgd.gardenexpo.entity.*;
import com.htgd.gardenexpo.service.CommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author: 王秀田
 * @date: 2024/12/4 8:46
 * @description: 消息处理类
 * 添加一个处理过期的消息,写个定时任务,间隔1s轮询延时队列中已到期的任务,如果获取不到为空,
 * 则不进行消息处理的逻辑 , 反之继续轮询
 */
@Slf4j
@Service
public class DelayMessageService {

    @Autowired
    private DelayMessageMapper delayMessageMapper;

    @Autowired
    private GeConCompetitionSportsMapper geConCompetitionSportsMapper;

    @Autowired
    private GeConLeisureSportsMapper geConLeisureSportsMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String DELAYED_MESSAGES_ZSET = "delayed:messages";

    @Autowired
    private GeConTheaterSeatMapper geConTheaterSeatMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private GeConUserCompeteMapper geConUserCompeteMapper;

    @Autowired
    private GeConMealOrderMapper geConMealOrderMapper;

    /**
     * 处理已到期的消息(轮询)
     */
    @Transactional
    @Scheduled(fixedRate = 1000)
    public void processMessages() {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        long now = System.currentTimeMillis();
        Set<ZSetOperations.TypedTuple<String>> messages = redisTemplate.opsForZSet()
                .rangeByScoreWithScores(DELAYED_MESSAGES_ZSET, 0, now);
//        log.info(now + " 待处理消息数量： " + messages.size());
        if (messages != null && !messages.isEmpty()) {
            for (ZSetOperations.TypedTuple<String> message : messages) {
                CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                    System.out.println(now + " :" + message.getValue() + " --> 消息开始处理");
                    try {
                        //  2.1.1 : 业务任务的处理时间(实际可能会更长)
                        DelayMessage delayMessage = JSONObject.parseObject(message.getValue(),
                                DelayMessage.class);
                        String msg = message.getValue();
                        long score = message.getScore().longValue();
                        if(Objects.equals(delayMessage.getStatus(),"1")&&Objects.equals(delayMessage.getType(),"1")){
                            //赛事运动 开始
                            if(score <= now){
                                GeConCompetitionSports conCompetitionSports = JSONObject.parseObject(delayMessage.getContent(),
                                        GeConCompetitionSports.class);
                                GeConCompetitionSports conCompetitionSports1 = new GeConCompetitionSports();
                                conCompetitionSports1.setId(conCompetitionSports.getId());
                                conCompetitionSports1.setActive("1");
                                geConCompetitionSportsMapper.updateById(conCompetitionSports1);
                                geConUserCompeteMapper.updateScoreStatusByMotionId(1,conCompetitionSports.getId());
                            }
                        }
                        if(Objects.equals(delayMessage.getStatus(),"2")&&Objects.equals(delayMessage.getType(),"1")){
                            //赛事运动 结束
                            if(score <= now){
                                GeConCompetitionSports conCompetitionSports = JSONObject.parseObject(delayMessage.getContent(),
                                        GeConCompetitionSports.class);
                                GeConCompetitionSports conCompetitionSports1 = new GeConCompetitionSports();
                                conCompetitionSports1.setId(conCompetitionSports.getId());
                                conCompetitionSports1.setActive("2");
                                geConCompetitionSportsMapper.updateById(conCompetitionSports1);
                            }
                        }
                        if(Objects.equals(delayMessage.getStatus(),"1")&&Objects.equals(delayMessage.getType(),"2")){
                            //休闲运动 开始
                            if(score <= now){
                                GeConLeisureSports geConLeisureSports = JSONObject.parseObject(delayMessage.getContent(),
                                        GeConLeisureSports.class);
                                GeConLeisureSports conLeisureSports1 = new GeConLeisureSports();
                                conLeisureSports1.setId(geConLeisureSports.getId());
                                conLeisureSports1.setActive("1");
                                geConLeisureSportsMapper.updateById(conLeisureSports1);
                            }
                        }
                        if(Objects.equals(delayMessage.getStatus(),"2")&&Objects.equals(delayMessage.getType(),"2")){
                            //休闲运动 结束
                            if(score <= now){
                                GeConLeisureSports geConLeisureSports = JSONObject.parseObject(delayMessage.getContent(),
                                        GeConLeisureSports.class);
                                GeConLeisureSports conLeisureSports1 = new GeConLeisureSports();
                                conLeisureSports1.setId(geConLeisureSports.getId());
                                conLeisureSports1.setActive("2");
                                geConLeisureSportsMapper.updateById(conLeisureSports1);
                            }
                        }
                        //设备订单
                        if(Objects.equals(delayMessage.getType(),"3")){
                            if(score <= now){
                                GeConMealOrder geConMealOrder = JSONObject.parseObject(delayMessage.getContent(),
                                        GeConMealOrder.class);
                                geConMealOrder.setStatus("1");
                                geConMealOrderMapper.updateById(geConMealOrder);
                            }
                        }
                        System.out.println("Processing message: " + msg);
                        redisTemplate.opsForZSet().remove(DELAYED_MESSAGES_ZSET, msg);
                        delayMessageMapper.deleteById(delayMessage.getId());
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    return "处理完成";
                }, executor);
            }
        }
    }

    /**
     * 每天凌晨重置影院座位
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void configureTasks() {
        System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
        GeConTheaterSeat geConTheaterSeat = geConTheaterSeatMapper.selectById(1);
        JSONArray jsonArray = JSONArray.parseArray(geConTheaterSeat.getSeat());
        JSONArray seatList = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject seat = new JSONObject();
            String element = jsonArray.getString(i);
            JSONObject jsonObject = JSONObject.parseObject(element);
            String value = (String) jsonObject.get("value");
            seat.put("value",value);
            seat.put("status","0");
            seatList.add(seat);
        }
        GeConTheaterSeat geConTheaterSeat1 = new GeConTheaterSeat();
        geConTheaterSeat1.setId(1);
        geConTheaterSeat1.setSeat(seatList.toJSONString());
        geConTheaterSeat1.setUpdateTime(LocalDateTime.now());
        geConTheaterSeatMapper.updateById(geConTheaterSeat1);
    }

    /**
     * 每小时去查询赛事结果并更新
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void configureTask() {
        System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
        //需要查询用户赛事结果并修改
        List<GeConUserCompete> geConUserCompeteList = geConUserCompeteMapper.selectList(
                new LambdaQueryWrapper<GeConUserCompete>()
                .eq(GeConUserCompete::getStatus,"0")
                .isNull(GeConUserCompete::getSumMileage)
                .isNull(GeConUserCompete::getSumDuration)
                .ne(GeConUserCompete::getScoreStatus,0));
        geConUserCompeteList.stream().forEach(item->{
            commonService.getUserSportData(item.getMotionId(),item.getUserId().toString());
        });
    }
}
